package mypack;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;

import org.apache.hadoop.io.Writable;

public class Chromosome implements Writable {
	public int mGenMap[];
	public int parent1[];
	public int parent2[];
	public int mPathLength;
	public float mFitness=0;
	public int mRankFitness = 0;
	int crossPoint1;
	int crossPoint2;
	int numberOfChosen=0;
	int populationId;
	//int orderInPopulation;
	int generationNumber;
	boolean mutated;
	int prevPop = -1;
	
	
	public Chromosome(int pGenMap[])
	{
		mGenMap = pGenMap;
	}

	public Chromosome()
	{
		mGenMap = new int[Global.CHROMOSOME_LENGTH];
		parent1 = new int[Global.CHROMOSOME_LENGTH];
		parent2 = new int[Global.CHROMOSOME_LENGTH];
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			mGenMap[i] = -1;
			parent1[i] = -1;
			parent2[i] = -1;
			
		}
		mPathLength = 0;
		mFitness = 0;
		populationId = -1;
		//orderInPopulation = -1;
		generationNumber = -1;
		mutated = false;
	}
	
	public void calculatePathLength()
	{
		int dist = 1000;
		int index1 = -1;
		int index2 = -2;
		mPathLength = 0;
		for (int i = 0; i < Global.CHROMOSOME_LENGTH-1; i++) 
		{
			index1 = mGenMap[i];
			index2 = mGenMap[i+1];
			if (index1 < 0 || index2 < 0) 
			{
				System.out.println("index1: "+index1);
				System.out.println("index2: "+index2);
			}
			else
			{
				dist = Global.gen.AdjencyMatrix[index1][index2];
			}
			mPathLength += dist;
		}
		index1 = mGenMap[Global.CHROMOSOME_LENGTH-1];
		index2 = mGenMap[0];
		dist = Global.gen.AdjencyMatrix[index1][index2];
		mPathLength += dist;
	}
	
	public boolean isCityInTheTour(int cityID)
	{
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			if (mGenMap[i] == cityID) 
			{
				return true;
			}
		}
		return false;
	}
	
	public Chromosome copyChromosome()
	{
		Chromosome newOne = new Chromosome();
		newOne.crossPoint1 = crossPoint1;
		newOne.crossPoint2 = crossPoint2;
		newOne.mFitness = mFitness;
		newOne.mGenMap = Arrays.copyOf(mGenMap, Global.CHROMOSOME_LENGTH);
		newOne.mPathLength = mPathLength;
		newOne.parent1 = Arrays.copyOf(parent1, Global.CHROMOSOME_LENGTH);
		newOne.parent2 = Arrays.copyOf(parent2, Global.CHROMOSOME_LENGTH);
		newOne.populationId = populationId;
		//newOne.orderInPopulation = orderInPopulation;
		newOne.generationNumber = generationNumber;
		newOne.mutated = mutated;
		newOne.prevPop = prevPop;
		newOne.mRankFitness = mRankFitness;
		return newOne;
	}

	@Override
	public void readFields(DataInput in) throws IOException 
	{
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			mGenMap[i] = in.readInt();
		}
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			parent1[i] = in.readInt();
		}
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			parent2[i] = in.readInt();
		}
		mPathLength = in.readInt();
		mFitness = in.readFloat();
		crossPoint1 = in.readInt();
		crossPoint2 = in.readInt();
		populationId = in.readInt();
		//orderInPopulation = in.readInt();
		generationNumber = in.readInt();
		mutated = in.readBoolean();
		prevPop = in.readInt();
		mRankFitness = in.readInt();
	}

	@Override
	public void write(DataOutput out) throws IOException 
	{
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			 out.writeInt(mGenMap[i]);
		}
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			 out.writeInt(parent1[i]);
		}
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			 out.writeInt(parent2[i]);
		}
		out.writeInt(mPathLength);
		out.writeFloat(mFitness);
		out.writeInt(crossPoint1);
		out.writeInt(crossPoint2);
		out.writeInt(populationId);
		//out.writeInt(orderInPopulation);
		out.writeInt(generationNumber);
		out.writeBoolean(mutated);
		out.writeInt(prevPop);
		out.writeInt(mRankFitness);		
	}
	
	public String toString()
	{
		String retVal="";
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			 retVal+="-"+mGenMap[i];
		}
		retVal+="\t";
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			 retVal+="-"+parent1[i];
		}
		retVal+="\t";
		for (int i = 0; i < Global.CHROMOSOME_LENGTH; i++) 
		{
			retVal+="-"+parent2[i];
		}
		retVal+="\t";
		retVal += mPathLength+" ";
		retVal += mFitness+" ";
		retVal += crossPoint1+" ";
		retVal += crossPoint2+" ";
		retVal += populationId+" ";
		//retVal += orderInPopulation+" ";
		retVal += generationNumber+" ";
		retVal += mutated+" ";
		retVal += prevPop+" ";
		retVal += mRankFitness+"\n";
		
		
		return retVal;
	}
	
	public boolean isSame(Chromosome pChromosome)
	{
		for (int i = 0; i < mGenMap.length; i++) 
		{
			if (this.mGenMap[i] != pChromosome.mGenMap[i]) 
			{
				return false;
			}
		}
		return true;
	}
	
	public int similarityPercentage(Chromosome pChoromosome)
	{
		int sameGenNumber=0;
		for(int i = 0; i < Global.CHROMOSOME_LENGTH; i++)
		{
			if(mGenMap[i] == pChoromosome.mGenMap[i])
			{
				sameGenNumber++;
			}
		}
		
		return (100 * sameGenNumber / Global.CHROMOSOME_LENGTH);
	}
}
